﻿Shader "Aniya/GiantGround"
{
    Properties
    {
		[CurvedWorldBendSettings] _CurvedWorldBendSettings("5|1|1", Vector) = (0, 0, 0, 0)

        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _NormalTex ("NormalHeight", 2D) = "white" {}
        _Glossiness ("Smoothness", Range(0,1)) = 0.5
        _Metallic ("Metallic", Range(0,1)) = 0.0
		_UVScale ("UVScale", Float) = 1

		_HeightOffset("Height Offset", Float) = 0

		_BumpMap("Normal Map（地面）", 2D) = "bump" {}
		_BumpMapHor("Normal Map（峭面）", 2D) = "bump" {}
		_BumpScale("Bump UV Scale（地面）", float) = 6
		_BumpScale2("Bump UV Scale（地面2）", float) = 6
		_BumpScaleHor("Bump UV Scale（峭面）", float) = 10
		_BumpIntensity("Normal Map Intensity（地面）", float) = 1
		_BumpIntensity2("Normal Map Intensity（地面2）", float) = 1
		_BumpIntensityHor("Normal Map Intensity（峭面）", float) = 1
		_TriplanarBlendSharpness("Blend Sharpness",float) = 1

		_NormalFactor("Normal Factor", float) = 1
		_NormalMove("Normal Move", vector) = (0,0,0,0)

    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 200
		Cull Off

        CGPROGRAM
        // Physically based Standard lighting model, and enable shadows on all light types
        #pragma surface surf Standard vertex:vertGround fullforwardshadows nolightmap nometa exclude_path:forward

        // Use shader model 3.0 target, to get nicer looking lighting
        #pragma target 3.0

		#define CURVEDWORLD_BEND_TYPE_LITTLEPLANET_Y
		#define CURVEDWORLD_BEND_ID_1
		#pragma shader_feature_local CURVEDWORLD_DISABLED_ON
		#pragma shader_feature_local CURVEDWORLD_NORMAL_TRANSFORMATION_ON
		#include "Assets/Amazing Assets/Curved World/Shaders/Core/CurvedWorldTransform.cginc"

        sampler2D _MainTex;
        sampler2D _NormalTex;

		struct appdata {
			float4 vertex : POSITION;
			float4 tangent : TANGENT;
			float3 normal : NORMAL;
			//float2 texcoord : TEXCOORD0;
		};

        struct Input
        {
			half3 groundColor;
            //float2 worldUV;
			float3 posWorld;
			//float3 normalInput;
			float3 unpackNormal;
			float3 worldNormal; INTERNAL_DATA 
        };

        half _Glossiness;
        half _Metallic;
        fixed4 _Color;
		float _UVScale;
		float _HeightOffset;

		sampler2D _BumpMap;
		float4 _BumpMap_ST;
		sampler2D _BumpMapHor;
		float4 _BumpMapHor_ST;
		float _BumpScale;
		float _BumpScale2;
		float _BumpScaleHor;
		float _BumpIntensity;
		float _BumpIntensity2;
		float _BumpIntensityHor;
		float _TriplanarBlendSharpness;

		float _NormalFactor;
		float4 _NormalMove;

		
		float3 getDetailNormalLOD(float3 worldPos, float3 worldNormal) 
		{
			half2 yUV = worldPos.xz / _BumpScale;
			half2 yUV2 = worldPos.xz / _BumpScale2;
			half2 xUV = worldPos.zy / _BumpScaleHor;
			half2 zUV = worldPos.xy / _BumpScaleHor;
			yUV = TRANSFORM_TEX(yUV, _BumpMap);
			yUV2 = TRANSFORM_TEX(yUV2, _BumpMap);
			xUV = TRANSFORM_TEX(xUV, _BumpMapHor);
			zUV = TRANSFORM_TEX(zUV, _BumpMapHor);
			half3 yDiff = UnpackNormal(tex2Dlod(_BumpMap, half4(yUV,0,1)));
			half3 yDiff2 = UnpackNormal(tex2Dlod(_BumpMap, half4(yUV2,0,1)));
			half3 xDiff = UnpackNormal(tex2Dlod(_BumpMapHor, half4(xUV,0,1)));
			half3 zDiff = UnpackNormal(tex2Dlod(_BumpMapHor, half4(zUV,0,1)));

			yDiff.xy *= _BumpIntensity;
			yDiff2.xy *= _BumpIntensity2;
			xDiff.xy *= _BumpIntensityHor;
			zDiff.xy *= _BumpIntensityHor;

			half3 blendWeights = pow(abs(worldNormal), _TriplanarBlendSharpness);

			return xDiff * blendWeights.x + (yDiff + yDiff2)* blendWeights.y + zDiff * blendWeights.z;
		}

		float3 getDetailNormal(float3 worldPos, float3 worldNormal) 
		{
			//worldNormal = UnpackNormal(float4(worldNormal, 1));
			half2 yUV = worldPos.xz / _BumpScale;
			half2 yUV2 = 1-worldPos.xz / _BumpScale2;
			half2 xUV = worldPos.zy / _BumpScaleHor;
			half2 zUV = worldPos.xy / _BumpScaleHor;
			yUV = TRANSFORM_TEX(yUV, _BumpMap);
			yUV2 = TRANSFORM_TEX(yUV2, _BumpMap);
			xUV = TRANSFORM_TEX(xUV, _BumpMapHor);
			zUV = TRANSFORM_TEX(zUV, _BumpMapHor);
			half3 yDiff = UnpackNormal(tex2D(_BumpMap, yUV));
			half3 yDiff2 = UnpackNormal(tex2D(_BumpMap, yUV2));
			half3 xDiff = UnpackNormal(tex2D(_BumpMapHor, xUV));
			half3 zDiff = UnpackNormal(tex2D(_BumpMapHor, zUV));

			yDiff.xy *= _BumpIntensity;
			yDiff2.xy *= _BumpIntensity2;
			xDiff.xy *= _BumpIntensityHor;
			zDiff.xy *= _BumpIntensityHor;

			half3 blendWeights = pow(abs(worldNormal), _TriplanarBlendSharpness);
			blendWeights = blendWeights / (blendWeights.x + blendWeights.y + blendWeights.z);
			float3 normalMap = xDiff * blendWeights.x + (yDiff + yDiff2)* blendWeights.y + zDiff * blendWeights.z;
			return normalMap;
		}


		void vertGround(inout appdata v, out Input o) 
		{
			UNITY_SETUP_INSTANCE_ID(v);
			UNITY_INITIALIZE_OUTPUT(Input, o);
			UNITY_TRANSFER_INSTANCE_ID(v, o);
			UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);

			float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
			float2 worldPosUV = worldPos.xz / _UVScale;
			float4 uv4 = float4(worldPosUV, 0, 0);
			half4 normalHeight = tex2Dlod(_NormalTex, uv4);
			half3 unpackNormal = normalHeight.xzy * 2 - 1;
			unpackNormal.xz *= _NormalFactor;
			//normalHeight.z = sqrt(1.0 - saturate(dot(normalHeight.xy, normalHeight.xy)));
			
			//v.normal = unpackNormal * 0.5 + 0.5;
			float height = normalHeight.a * 100;
			worldPos.y = height + _HeightOffset;
			//o.worldUV = worldPosUV;
			o.posWorld = worldPos;
			o.unpackNormal = unpackNormal;
			v.vertex.xyz = mul(unity_WorldToObject, float4(worldPos, 1));
			//detailNormal = detailNormal * unpackNormal;
			//v.vertex.x += detailNormal.x * _NormalMove.x;
			//v.vertex.y += detailNormal.y * _NormalMove.y;
			//v.vertex.z += detailNormal.z * _NormalMove.z;
			
			v.normal = unpackNormal*0.5+0.5;
			float3 binormal = cross(unpackNormal, fixed3(1, 0, 0));
			float3 afterTangent = cross(unpackNormal, binormal);
			v.tangent.xyz = afterTangent;
			v.tangent.w = 1;

			//由CurvedWorld来更新法线
			#if defined(CURVEDWORLD_IS_INSTALLED) && !defined(CURVEDWORLD_DISABLED_ON)
			   #ifdef CURVEDWORLD_NORMAL_TRANSFORMATION_ON
				  CURVEDWORLD_TRANSFORM_VERTEX_AND_NORMAL(v.vertex, v.normal, v.tangent)
			   #else
				  CURVEDWORLD_TRANSFORM_VERTEX(v.vertex)
			   #endif
			#endif

			o.groundColor = tex2Dlod (_MainTex, uv4) * _Color;
			//float3 detailNormal = getDetailNormalLOD(o.posWorld, unpackNormal);
			//float3 binormal = cross(v.normal, fixed3(1, 0, 0));
			//float3 afterTangent = cross(v.normal, binormal);
			//float3 moveNormal = normalize(unpackNormal + detailNormal * _NormalFactor);
			//v.vertex.xyz +=moveNormal*(_NormalMove.xyz + _NormalMove.w);
			//v.vertex.xyz += (detailNormal.x * afterTangent + detailNormal.y * binormal + detailNormal.z * unpackNormal) * 
			//			(_NormalMove.xyz + _NormalMove.w);
						
			//v.vertex.xyz += afterTangent * (_NormalMove.x + _NormalMove.w);
			//v.vertex.xyz += binormal * (_NormalMove.y + _NormalMove.w);
			//v.vertex.xyz += unpackNormal * (_NormalMove.z + _NormalMove.w);
		}

        void surf (Input IN, inout SurfaceOutputStandard o)
        {
			//float3 worldNormal = WorldNormalVector (IN, half3(0,0,1)); //IN.normalInput;// 
			float3 normalWS = WorldNormalVector(IN, half3(0,1,0));
			//float3 normalWS = IN.worldNormal;
			//float3 modifyNormal = getDetailNormal(IN.posWorld, normalWS);
			//o.Normal = normalize( ( cross( ddx( IN.worldPos ) , ddy( IN.worldPos ) ) + float3( 1E-09,0,0 ) ) );

			float3 modifyNormal = normalize(getDetailNormal(IN.posWorld, IN.unpackNormal));
			//float3 modifyNormal = normalize(getDetailNormal(IN.posWorld, normalWS));
			o.Normal = modifyNormal;

			//half4 nc = tex2D(_NormalTex, IN.worldUV);
            //fixed4 c = tex2D (_MainTex, IN.worldUV) * _Color;
            o.Albedo = IN.groundColor * lerp(_Color.a, 1, saturate(abs(modifyNormal.z)));// (1-(abs(modifyNormal.x) + abs(modifyNormal.y)));
            // Metallic and smoothness come from slider variables
            o.Metallic = _Metallic;
            o.Smoothness = _Glossiness;
            //o.Alpha = c.a;
        }
        ENDCG


		Pass{
			Name "ShadowCaster"
			Tags { "LightMode" = "ShadowCaster" }

			ZWrite On ZTest LEqual

			CGPROGRAM
			#pragma target 3.0

			// -------------------------------------


			#pragma shader_feature_local _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
			#pragma shader_feature_local _METALLICGLOSSMAP
			#pragma shader_feature_local _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
			#pragma shader_feature_local _PARALLAXMAP
			#pragma multi_compile_shadowcaster
			#pragma multi_compile_instancing
			// Uncomment the following line to enable dithering LOD crossfade. Note: there are more in the file to uncomment for other passes.
			//#pragma multi_compile _ LOD_FADE_CROSSFADE



#pragma shader_feature_local CURVEDWORLD_BEND_TYPE_CLASSICRUNNER_X_POSITIVE CURVEDWORLD_BEND_TYPE_LITTLEPLANET_Y CURVEDWORLD_BEND_TYPE_CYLINDRICALTOWER_X CURVEDWORLD_BEND_TYPE_SPIRALHORIZONTAL_X_POSITIVE CURVEDWORLD_BEND_TYPE_SPIRALHORIZONTALDOUBLE_X CURVEDWORLD_BEND_TYPE_SPIRALVERTICAL_X_POSITIVE CURVEDWORLD_BEND_TYPE_SPIRALVERTICAL_X_NEGATIVE CURVEDWORLD_BEND_TYPE_TWISTEDSPIRAL_X_POSITIVE CURVEDWORLD_BEND_TYPE_CYLINDRICALROLLOFF_Z
#define CURVEDWORLD_BEND_ID_1
#pragma shader_feature_local CURVEDWORLD_DISABLED_ON
#pragma shader_feature_local CURVEDWORLD_NORMAL_TRANSFORMATION_ON



			#pragma vertex vertShadowCaster
			#pragma fragment fragShadowCaster
			#include "UnityStandardShadow.cginc"

			ENDCG
		}
    }
    FallBack "Diffuse"
}
